package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrderService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.*;
import io.swagger.util.Json;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 赵星
 * @version 1.0
 * @Date 2023/9/27 21:06
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 用户下单
     *
     * @param ordersSubmitDTO
     * @return
     */
    @Override
    @Transactional
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        //先判断地址是否为空，为空不能下单
        AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        //判断购物车是否为空，为空不能下单
        Long userId = BaseContext.getCurrentId();
        ShoppingCart shoppingCart = new ShoppingCart();
        shoppingCart.setUserId(userId);
        List<ShoppingCart> shoppingCartlist = shoppingCartMapper.list(shoppingCart);
        if (shoppingCartlist == null || shoppingCartlist.size() == 0) {
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }

        //向订单表插入一条数据
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setPhone(addressBook.getPhone());
        orders.setConsignee(addressBook.getConsignee());
        orders.setUserId(userId);
        orderMapper.insert(orders);

        List<OrderDetail> orderDetailList = new ArrayList<>();
        //向订单详细表插入n条数据
        for (ShoppingCart cart : shoppingCartlist) {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(cart, orderDetail);
            orderDetail.setOrderId(orders.getId());
            orderDetailList.add(orderDetail);
        }
        orderDetailMapper.insertBatch(orderDetailList);
        //清空购物车数据
        shoppingCartMapper.delete(shoppingCart);
        //封装VO结果返回
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderTime(orders.getOrderTime())
                .orderAmount(orders.getAmount())
                .orderNumber(orders.getNumber())
                .build();
        return orderSubmitVO;
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO
     * @return
     */
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.getById(userId);

//        //调用微信支付接口，生成预支付交易单
//        JSONObject jsonObject = weChatPayUtil.pay(
//                ordersPaymentDTO.getOrderNumber(), //商户订单号
//                new BigDecimal(0.01), //支付金额，单位 元
//                "苍穹外卖订单", //商品描述
//                user.getOpenid() //微信用户的openid
//        );

//        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
//            throw new OrderBusinessException("该订单已支付");
//        }
//
//        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
//        vo.setPackageStr(jsonObject.getString("package"));

        String orderNumber = ordersPaymentDTO.getOrderNumber();
        paySuccess(orderNumber);

        return null;
    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo
     */
    public void paySuccess(String outTradeNo) {

        // 根据订单号查询订单
        Orders ordersDB = orderMapper.getByNumber(outTradeNo);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        orderMapper.update(orders);

        //通过websocket向客户推送来单提醒
        HashMap<String, Object> map = new HashMap<>();
        map.put("type", 1);//1 : 来单提醒， 2 : 客户催单
        map.put("orderId", ordersDB.getId());
        map.put("content", "订单号:" + outTradeNo);
        String json = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(json);
    }

    @Override
    public PageResult pageQuery(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        Page<OrderPageVo> page = orderMapper.pageQuery(BaseContext.getCurrentId(), ordersPageQueryDTO.getStatus());
        List<OrderPageVo> result = page.getResult();
        for (OrderPageVo orderPageVo : result) {
            //根据订单id查订单详情
            List<OrderDetail> list = orderDetailMapper.selectDetailByOrderId(orderPageVo.getId());
            orderPageVo.setOrderDetailList(list);
        }

        PageResult pageResult = new PageResult();
        pageResult.setTotal((page.getTotal()));
        pageResult.setRecords(page.getResult());
        return pageResult;
    }

    /**
     * 获取订单详情
     *
     * @param id
     * @return
     */
    @Override
    public OrderPageVo getOrderDetail(Long id) {
        OrderPageVo orderPageVo = orderMapper.selectOrderById(id);//根据订单id查询订单
        //根据订单id查询订单详情
        List<OrderDetail> orderDetailList = orderDetailMapper.selectDetailByOrderId(id);
        orderPageVo.setOrderDetailList(orderDetailList);

        //获取地址
        AddressBook addressBook = addressBookMapper.getByOrderId(id);
        String address = addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail();
        orderPageVo.setAddress(address);
        return orderPageVo;
    }

    @Override
    public void cancel(Integer id) throws Exception {
        // 根据id查询订单
        String idStr = id + "";
        Long idL = Long.valueOf(idStr);
        OrderPageVo orderPageVo = orderMapper.selectOrderById(idL);

        // 校验订单是否存在
        if (orderPageVo == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        if (orderPageVo.getStatus() > 2) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        Orders orders = new Orders();
        orders.setId(orderPageVo.getId());

        // 订单处于待接单状态下取消，需要进行退款
        if (orderPageVo.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
            //调用微信支付退款接口
//            weChatPayUtil.refund(
//                    orderPageVo.getNumber(), //商户订单号
//                    orderPageVo.getNumber(), //商户退款单号
//                    new BigDecimal(0.01),//退款金额，单位 元
//                    new BigDecimal(0.01));//原订单金额

            //支付状态修改为 退款
            orders.setPayStatus(Orders.REFUND);
        }

        // 更新订单状态、取消原因、取消时间
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelReason("用户取消");
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    @Override
    //再来一单
    public void again(Long id) {
        //根据订单id查询订单详情
        List<OrderDetail> list = orderDetailMapper.selectDetailByOrderId(id);
        for (OrderDetail orderDetail : list) {
            ShoppingCart shoppingCart = new ShoppingCart();
            shoppingCart.setUserId(BaseContext.getCurrentId());
            BeanUtils.copyProperties(orderDetail, shoppingCart);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCartMapper.insert(shoppingCart);
        }
    }

    @Override
    //订单搜索
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        Page<OrderVO> page = orderMapper.conditionSearch(ordersPageQueryDTO);
        List<OrderVO> result = page.getResult();//所有的订单
        for (OrderVO orderVO : result) {
            //根据每个订单查询菜品
            List<OrderDetail> orderDetailList = orderDetailMapper.selectDishListByOrderId(orderVO.getId());
            StringBuilder orderDish = new StringBuilder();
            for (OrderDetail orderDetail : orderDetailList) {//拼接该订单下单所有菜品
                orderDish.append(orderDetail.getName()).append("*").append(orderDetail.getNumber()).append(";");
            }
            orderVO.setOrderDishes(orderDish.toString());
            //获取地址
            AddressBook addressBook = addressBookMapper.getByOrderId(orderVO.getId());
            String address = addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail();
            orderVO.setAddress(address);

        }
        PageResult pageResult = new PageResult();
        pageResult.setTotal(page.getTotal());
        pageResult.setRecords(page.getResult());
        return pageResult;
    }

    @Override
    public OrderStatisticsVO getStatistics() {
        Integer confirmed = orderMapper.selectStatistics(Orders.CONFIRMED);//待派送数量
        Integer deliveryInProgress = orderMapper.selectStatistics(Orders.DELIVERY_IN_PROGRESS);//派送中数量
        Integer toBeConfirmed = orderMapper.selectStatistics(Orders.TO_BE_CONFIRMED);//待结单数量
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        orderStatisticsVO.setConfirmed(confirmed);
        orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        return orderStatisticsVO;
    }

    @Override
    //接单
    public void confirm(OrdersConfirmDTO ordersConfirmDTO) {
        Orders orders = new Orders();
        orders.setId(ordersConfirmDTO.getId());
        orders.setStatus(Orders.CONFIRMED);
        orderMapper.update(orders);
    }

    @Override
    //拒单
    public void rejection(OrdersRejectionDTO ordersRejectionDTO) {
        Orders orders = new Orders();
        orders.setId(ordersRejectionDTO.getId());
        orders.setRejectionReason(ordersRejectionDTO.getRejectionReason());
        orders.setStatus(7);//设置订单状态为已退款
        orders.setPayStatus(2);//设置支付状态为退款
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    @Override
    public void cancelByAdmin(OrdersCancelDTO ordersCancelDTO) {
        Orders orders = new Orders();
        orders.setId(ordersCancelDTO.getId());
        orders.setCancelReason(ordersCancelDTO.getCancelReason());
        orders.setStatus(Orders.CANCELLED);//设置订单状态为已退款
        orders.setPayStatus(2);//设置支付状态为退款
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    @Override
    public void delivery(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
        orderMapper.update(orders);
    }

    @Override
    public void complete(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.COMPLETED);
        orders.setDeliveryTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    @Override
    public void reminder(Long id) {
        OrderPageVo orderPageVo = orderMapper.selectOrderById(id);
        if (orderPageVo == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //通过websocket向客户端推送催单提醒
        HashMap<String, Object> map = new HashMap<>();
        map.put("type", 2);//1 : 来单提醒， 2 : 客户催单
        map.put("orderId", id);
        map.put("content", "订单号:" + orderPageVo.getNumber());
        String json = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(json);
    }

    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        Integer totalOrderCount = 0;//订单总数
        Integer validOrderCount = 0;//有效订单数
        Double orderCompletionRate = 0.0;//订单完成率

        ArrayList<LocalDate> dataList = new ArrayList<>();
        while (!begin.equals(end)) {
            dataList.add(begin);
            begin = begin.plusDays(1);
        }
        dataList.add(end);

        ArrayList<Integer> orderCountList = new ArrayList<>();//每日订单数
        ArrayList<Integer> validOrderCountList = new ArrayList<>();//每日有订单数
        for (LocalDate localDate : dataList) {
            LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);

            HashMap<String, Object> map = new HashMap<>();
            map.put("end", endTime);
            map.put("begin", beginTime);
            //查询订单总数
            Integer countAll = orderMapper.countAllByMap(map);
            orderCountList.add(countAll);
            if (countAll != null && countAll != 0) {
                totalOrderCount += countAll;
            }

            map.put("status", Orders.COMPLETED);
            //查询有效订单数
            Integer count = orderMapper.countAllByMap(map);
            validOrderCountList.add(count);
            if (count != null && count != 0) {
                validOrderCount += count;
            }
        }

        //计算订单完成率
        if (totalOrderCount != 0) {
            orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;
        }


        return OrderReportVO.builder()
                .dateList(StringUtils.join(dataList, ","))
                .totalOrderCount(totalOrderCount)
                .validOrderCountList(StringUtils.join(validOrderCountList, ","))
                .validOrderCount(validOrderCount)
                .orderCountList(StringUtils.join(orderCountList, ","))
                .orderCompletionRate(orderCompletionRate)
                .build();
    }

    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {

        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        HashMap<String, Object> map = new HashMap<>();
        map.put("begin", beginTime);
        map.put("end", endTime);
        //查询当天出现的菜品名
        List<GoodsSalesDTO> list = orderMapper.getDishNameByMap(map);
        ArrayList<String> nameList = (ArrayList<String>) list.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
        ArrayList<Integer> numberList = (ArrayList<Integer>) list.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());


        return SalesTop10ReportVO.builder()
                .nameList(StringUtils.join(nameList, ","))
                .numberList(StringUtils.join(numberList, ","))
                .build();
    }
}
